/**
 * huize Service Inc
 * All Rights Reserved @2018
 */
package com.huize.ladon.apm.common.enums;

import org.apache.commons.lang3.StringUtils;

import java.util.stream.Stream;

/**
 * 描述: IP划分类型
 *
 * @author tianyuliang
 * @version $Id: IpZoneTypeEnum.java, v0.1 2019/12/25
 */
public enum IpZoneTypeEnum implements EnumInterface {

    /**
     * 未知IP
     */
    UNKNOWN("unknown", "未知IP"),

    /**
     * 外网IP(特殊的公网IP，是运维额外加入的类型，保留即可)
     */
    PRODUCTION_IP("production", "外网IP"),

    /**
     * 内网IP
     */
    INTERNAL_IP("internal", "内网IP"),

    /**
     * 公网IP
     */
    PUBLIC_IP("public", "公网IP");

    /**
     * 模糊IP符号 *号
     */
    public static final String FUZZY_IP_SYMBOL = "*";

    /**
     * IP数字最小值0
     */
    public static final Integer MIN_IP_NUMBER = 0;

    /**
     * IP数字最大值255
     */
    public static final Integer MAX_IP_NUMBER = 255;

    private String zone;

    private String desc;

    IpZoneTypeEnum(String zone, String desc) {
        this.zone = zone;
        this.desc = desc;
    }

    public static IpZoneTypeEnum of(String zoneType) {
        if (StringUtils.isBlank(zoneType)) {
            return UNKNOWN;
        }

        return Stream.of(values()).filter(b -> b.getCode().equalsIgnoreCase(zoneType.trim())).findFirst().orElse(UNKNOWN);
    }

    /**
     * 校验是否为公网IP
     *
     * @param zoneTypeEnum
     * @return
     */
    public static boolean isPublicIp(IpZoneTypeEnum zoneTypeEnum) {
        return zoneTypeEnum != null && (zoneTypeEnum == PUBLIC_IP || zoneTypeEnum == PRODUCTION_IP);
    }

    /**
     * 校验checkIp是否为“内网IP”,如果不是内网IP，那么就是公网IP
     *
     * @param fuzzyIp 私有IP匹配规则（10.160.*.*）
     * @param checkIp 待匹配的精确IP（10.160.2.97）
     * @return
     */
    public static IpZoneTypeEnum isInternalIp(String fuzzyIp, String checkIp) {
        if (StringUtils.isBlank(checkIp) || !checkIp.contains(".") || checkIp.split("\\.").length != 4) {
            return IpZoneTypeEnum.UNKNOWN;
        }

        String[] checkIps = checkIp.split("\\.");
        if (isFuzzyIpNumber(checkIps[0])) {
            return IpZoneTypeEnum.UNKNOWN;  // IP第一个位置的数字居然以 * 开始，则不识别这是什么IP
        }

        String[] fuzzyIps = fuzzyIp.split("\\.");
        // 匹配IP第1段数字
        if (!fuzzyIps[0].equalsIgnoreCase(checkIps[0])) {
            return IpZoneTypeEnum.PUBLIC_IP;
        }

        // 匹配IP第2段数字
        if (isFuzzyIpNumber(fuzzyIps[1])) {
            int value = Integer.parseInt(checkIps[1]);
            if (value >= MIN_IP_NUMBER && value <= MAX_IP_NUMBER) {
                return IpZoneTypeEnum.INTERNAL_IP;
            }
        } else {
            if (!fuzzyIps[1].equalsIgnoreCase(checkIps[1])) {
                return IpZoneTypeEnum.PUBLIC_IP;
            }
        }

        // 匹配IP第3段数字
        if (isFuzzyIpNumber(fuzzyIps[2])) {
            int value = Integer.parseInt(checkIps[2]);
            if (value >= MIN_IP_NUMBER && value <= MAX_IP_NUMBER) {
                return IpZoneTypeEnum.INTERNAL_IP;
            }
        } else {
            if (!fuzzyIps[2].equalsIgnoreCase(checkIps[2])) {
                return IpZoneTypeEnum.PUBLIC_IP;
            }
        }

        // 匹配IP第4段数字
        if (isFuzzyIpNumber(fuzzyIps[3])) {
            int value = Integer.parseInt(checkIps[3]);
            if (value >= MIN_IP_NUMBER && value <= MAX_IP_NUMBER) {
                return IpZoneTypeEnum.INTERNAL_IP;
            }
        } else {
            if (!fuzzyIps[3].equalsIgnoreCase(checkIps[3])) {
                return IpZoneTypeEnum.PUBLIC_IP;
            }
        }

        // 如果以上都匹配通过，则都是内网IP
        return IpZoneTypeEnum.INTERNAL_IP;
    }

    public static boolean isFuzzyIpNumber(String number) {
        return StringUtils.isNotBlank(number) && number.equalsIgnoreCase(FUZZY_IP_SYMBOL);
    }

    public String getZone() {
        return zone;
    }

    @Override
    public String getCode() {
        return zone;
    }

    @Override
    public String getDesc() {
        return desc;
    }

    @Override
    public String toString() {
        return String.format("IpZoneTypeEnum[%s, %s]", getZone(), getDesc());
    }

}
